package com.zxy.ziems.server.budget.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zxy.btp.common.response.PageResult;
import com.zxy.ziems.server.budget.convertor.BudgetDefConvertor;
import com.zxy.ziems.server.budget.convertor.BudgetValueConvertor;
import com.zxy.ziems.server.budget.mapper.BudgetDefMapper;
import com.zxy.ziems.server.budget.pojo.dto.BudgetDefDTO;
import com.zxy.ziems.server.budget.pojo.entity.BudgetDefEntity;
import com.zxy.ziems.server.budget.pojo.entity.BudgetValueEntity;
import com.zxy.ziems.server.budget.pojo.param.BudgetDefParam;
import com.zxy.ziems.server.budget.pojo.vo.BudgetManagerVO;
import com.zxy.ziems.server.budget.pojo.vo.BudgetValueVO;
import com.zxy.ziems.server.budget.service.BudgetDefService;
import com.zxy.ziems.server.budget.service.BudgetValueService;
import com.zxy.ziems.server.classify.pojo.entity.Classify;
import com.zxy.ziems.server.classify.service.ClassifyService;
import com.zxy.ziems.server.mybatis.core.query.QueryWrapperX;
import com.zxy.ziems.server.mybatis.core.service.ServiceImplX;
import com.zxy.ziems.server.statistics.pojo.param.BudgetQueryParam;
import com.zxy.ziems.server.utils.AssertUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class BudgetDefServiceImpl extends ServiceImplX<BudgetDefMapper, BudgetDefEntity> implements BudgetDefService {

    @Autowired
    private BudgetValueService budgetValueService;
    @Autowired
    private ClassifyService classifyService;

    @Transactional
    @Override
    public void add(BudgetDefDTO budgetDefDTO) {
        doCheckBeforeSaveAction(budgetDefDTO);

        BudgetDefEntity entity = BudgetDefConvertor.INSTANT.dto2Entity(budgetDefDTO);

        save(entity);
    }

    @Transactional
    @Override
    public void adds(List<BudgetDefDTO> budgetDefDTOs) {
        for (BudgetDefDTO budgetDefDTO : budgetDefDTOs) {
            add(budgetDefDTO);
        }
    }

    private void doCheckBeforeSaveAction(BudgetDefDTO budgetDefDTO) {
        Classify cla = classifyService.getById(budgetDefDTO.getClassifyId());
        AssertUtil.nonNull(cla, "未找到科室分类");
        QueryWrapper<BudgetDefEntity> param = new QueryWrapperX<>();
        param.lambda().eq(BudgetDefEntity::getClassifyId, budgetDefDTO.getClassifyId())
                .eq(BudgetDefEntity::getBudgetYear, budgetDefDTO.getBudgetYear());
        Long count = baseMapper.selectCount(param);
        AssertUtil.isFalse(count > 0, "科室标签已新增");
    }

    @Override
    public PageResult<BudgetManagerVO> page(BudgetDefParam param) {
        PageResult<BudgetDefEntity> pageResult = customPage(param, (page, aParam) -> baseMapper.queryList(page, aParam));
        if (pageResult.getTotal() < 1) {
            return new PageResult<>(0L, new ArrayList<>());
        }

        List<String> ids = pageResult.getList().stream().map(BudgetDefEntity::getId).collect(Collectors.toList());
        List<BudgetValueEntity> budgetValueEntities = budgetValueService.getByBudgetDefIds(ids);
        Map<String, List<BudgetValueEntity>> defValueMap = budgetValueEntities.stream().collect(Collectors.groupingBy(BudgetValueEntity::getBudgetDefId));
        List<BudgetManagerVO> list = pageResult.getList().stream().map(m -> {
            BudgetManagerVO vo = BudgetDefConvertor.INSTANT.entity2VO(m);
            buildMonthValue(vo, defValueMap.get(m.getId()));
            return vo;
        }).collect(Collectors.toList());

        return new PageResult<>(pageResult.getTotal(), list);
    }

    private void buildMonthValue(BudgetManagerVO vo, List<BudgetValueEntity> budgetValueEntities) {
        if (CollectionUtils.isEmpty(budgetValueEntities)) {
            return;
        }
        List<BudgetValueVO> valList = BudgetValueConvertor.INSTANT.EntityList2VoList(budgetValueEntities);
        Map<String, BudgetValueVO> monthMap = valList.stream().collect(Collectors.toMap(k -> String.format("%02d", k.getBudgetMonth()), v -> v, (e, e1) -> e));
        vo.setBudgetValueVOs(monthMap);
    }

    @Override
    public BudgetDefEntity getById(String budgetDefId) {
        return baseMapper.selectById(budgetDefId);
    }

    @Transactional
    @Override
    public void remove(List<String> ids) {
        List<BudgetDefEntity> budgetDefEntities = baseMapper.selectBatchIds(ids);
        AssertUtil.isFalse(CollectionUtils.isEmpty(budgetDefEntities) || budgetDefEntities.size() != ids.size(), "未找到预算信息");
        baseMapper.deleteBatchIds(ids);
        budgetValueService.deleteByBudgetDefIds(ids);
    }

    @Override
    public BudgetDefEntity get(BudgetQueryParam budgetQueryParam) {
        QueryWrapper<BudgetDefEntity> param = new QueryWrapper<>();
        param.lambda().eq(BudgetDefEntity::getBudgetYear, budgetQueryParam.getYear())
                .eq(BudgetDefEntity::getClassifyId, budgetQueryParam.getClassifyId());
        return baseMapper.selectOne(param);
    }
}
